// Kony

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "GameplayEffectTypes.h"
#include "BaseEffectActor.generated.h"

class UAbilitySystemComponent;
class UGameplayEffect;
//应用效果策略
UENUM(BlueprintType)
enum class EEffectApplicationPolicy
{
	ApplyOnOverlap, //应用效果
	ApplyOnEndOverlap, //结束时应用效果
	DoNotApply //不应用
};
//移除效果策略，这个实际上只用于配置无限时间效果的物体，其他的都会自行移除
UENUM(BlueprintType)
enum class EEffectRemovalPolicy
{
	RemoveOnEndOverlap, //移除效果
	DoNotRemoval //不移除
};



/**
 * 这个Actor 实现了一个物理碰撞触发器，当玩家进入这个Actor的碰撞范围时，会触发OnOverlap函数
 * 触发后获取到碰撞物体的Actor指针获取到对应的UBaseAttributeSet 数据集 来处理属性数据，demo实现了一个血瓶，角色碰撞后回血
 ***/
UCLASS()
class GASC_HUANLING_API ABaseEffectActor : public AActor
{
	GENERATED_BODY()
	
public:	
	ABaseEffectActor();
 
protected:
	virtual void BeginPlay() override;
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;

	
	//对目标应用效果函数
	UFUNCTION(BlueprintCallable)
	void ApplyEffectToActor(AActor* TargetActor,TSubclassOf<UGameplayEffect> GameplayEffectClass);
	//处理重叠事件
	UFUNCTION(BlueprintCallable)
	void OnOverlap(AActor* TargetActor);
	//处理结束重叠事件
	UFUNCTION(BlueprintCallable)
	void OnEndOverlap(AActor* TargetActor);
	//非无限效果，在效果应用时默认销毁
	UPROPERTY(EditAnywhere,BlueprintReadOnly, Category = "Applied Effect")
	bool bDestroyOnEffectRemovel = true;
	//敌人是否可用，如果为true，
	UPROPERTY(EditAnywhere,BlueprintReadOnly, Category = "Applied Effect")
	bool bApplyOnEffectEnemy = false;
	
	//即时生效效果类,让其可以在蓝图设置效果类型
	UPROPERTY(EditAnywhere,BlueprintReadOnly, Category = "Applied Effect")
	TSubclassOf<UGameplayEffect> InstantGameplayEffectClass;
	//即时生效效果 设置应用实例 默认设置不应用，在蓝图中自行选择
	UPROPERTY(EditAnywhere,BlueprintReadOnly, Category = "Applied Effect")
	EEffectApplicationPolicy InstantEffectApplicationPolicy = EEffectApplicationPolicy::DoNotApply;

	//持续时间效果类,让其可以在蓝图设置效果类型
	UPROPERTY(EditAnywhere,BlueprintReadOnly, Category = "Applied Effect")
	TSubclassOf<UGameplayEffect> DurationGameplayEffectClass;
	//持续时间效果 设置应用实例 默认设置不应用，在蓝图中自行选择
	UPROPERTY(EditAnywhere,BlueprintReadOnly, Category = "Applied Effect")
	EEffectApplicationPolicy DurationEffectApplicationPolicy = EEffectApplicationPolicy::DoNotApply;
	
	//无限时间效果类,让其可以在蓝图设置效果类型
	UPROPERTY(EditAnywhere,BlueprintReadOnly, Category = "Applied Effect")
	TSubclassOf<UGameplayEffect> InfiniteGameplayEffectClass;
	//无限时间效果 设置应用实例 默认设置不应用，在蓝图中自行选择
	UPROPERTY(EditAnywhere,BlueprintReadOnly, Category = "Applied Effect")
	EEffectApplicationPolicy InfiniteEffectApplicationPolicy = EEffectApplicationPolicy::DoNotApply;
	//无限时间效果 移除策略 默认设置移除
	UPROPERTY(EditAnywhere,BlueprintReadOnly, Category = "Applied Effect")
	EEffectRemovalPolicy InfiniteEffectRemovalPolicy = EEffectRemovalPolicy::RemoveOnEndOverlap;

	//将游戏效果处理映射到能力系统组件
	// ReSharper disable once CppUE4ProbableMemoryIssuesWithUObjectsInContainer
	TMap<FActiveGameplayEffectHandle,UAbilitySystemComponent*> ActiveEffectHandles;

	//物品等级 用于物品等级曲线表
	UPROPERTY(EditAnywhere,BlueprintReadOnly, Category = "Applied Effect")
	float ActorLevel = 1.f;

	// 是否启用飞向玩家功能
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Fly To Player")
	bool bEnableFlyToPlayer = false;

	// 飞向玩家的速度
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Fly To Player")
	float FlySpeed = 1200.0f;

	// 到达玩家的最小距离
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Fly To Player")
	float MinDistanceToPlayer = 50.0f;

	// 飞向玩家的更新频率（秒）
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Fly To Player")
	float FlyUpdateRate = 0.02f;

private:
	// 是否正在飞向玩家
	bool bIsFlyingToPlayer = false;

	// 目标玩家Actor
	TWeakObjectPtr<AActor> TargetPlayer;

	// 飞向玩家的Timer句柄
	FTimerHandle FlyToPlayerTimerHandle;

	// 飞向玩家的更新函数
	void UpdateFlyToPlayer();
	

	
	//堆叠效果Stacking 描述： 
	/**
	 * Aggregate by Source //按源聚合
	 * Stack Limit Count //堆叠限制数量 相同源施加的效果 不生效，不同源则叠加
	 * Stack Duration Refresh Policy //堆叠持续时间刷新策略 可以设置刷新或不刷新，不刷新就是吃多少个都不会刷新第一个的时间
	 * Stack Period Refresh Policy //堆叠持续时间刷新策略 可以设置刷新或不刷新，刷新就是会重置时间
	 * Stack Expiration Policy //移除堆叠效果策略 Clear Entire Stack //移除整个堆叠
	 * , Remove Sigle ...//移除单个， Refresh Duration //到期时候会刷新持续时间 会导致无线循环 不过可以OnStackCountChange callback来手动停止
	 ***/

	/**
	 * Aggregate by Target //按目标聚合
	 * Stack Limit Count //堆叠限制数量 在同一个目标中无论哪个来源 超出次数都不生效
	 * Stack Duration Refresh Policy //堆叠持续时间刷新策略 可以设置刷新或不刷新，刷新就是会重置第一个的时间
	 * 
	 ***/
};
